package com.db.concurrency;

import static org.junit.Assert.assertTrue;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.junit.After;
import org.junit.Before;

public abstract class ConcurrentHarness {

  protected static final int CYCLES = 500_000;
  protected ExecutorService executor;

  public ConcurrentHarness() {
    super();
  }

  @Before
  public void initExecutor() {
    executor = new ThreadPoolExecutor(4, 4, 5, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(CYCLES));
  }

  protected void submitTasks() {
    for (int i = 0; i < CYCLES; i++) {
      executor.submit(newTask());
    }
  }
  
  @After
  public void collectResults() throws InterruptedException {
    waitAllTasks();
    checkResults();
  }
  
  public void waitAllTasks() throws InterruptedException {
    executor.shutdown();
    boolean terminated = executor.awaitTermination(10, TimeUnit.SECONDS);
    assertTrue("Finished all tasks", terminated);
  }

  protected abstract void checkResults();

  protected abstract Runnable newTask();

}